#
# Program ID Number:consoleSubroutines.s
# Written by    :Beatris Rusu
# Date Created  :9/23/08
# Revision:	1.0
# Revisions made, date of revision, author:
#	First release   	Beatris Rusu

#--------------------------------------Console Subroutines---------------------------------------------

.text

# 
#Description: print a new line on the console 
#Internal registers used:  
#Declaration  (void)nextLine(void) 
###############
.globl nextLine
nextLine:
        addi 	$sp, $sp, -4    # Make space on stack.
        sw      $ra, 0($sp)     # Save return address.
	
	la	$a0, endl       # force end of line
        li	$v0, 4          # code for print string
	syscall                 # Print string 

retnextLine: 
        lw      $ra, 0($sp)     # Restore return address.
        addi    $sp, $sp, 4     # Restore stack pointer.
        jr      $ra		# Return.

# 
#Description: get input string from the console 
#Internal registers used:  
#Declaration  int inString(char *str) 
################
.globl inString 
inString:
        addi    $sp, $sp, -4   	# Make space on stack.
        sw      $ra, 0($sp)    	# Save return address.
           
        # simulator code to get string from console  
        # $a0 must contain pointer to input buffer
        li	$v0, 8  	# code for get string
        syscall                 # get string
        # $a1 contains length of string on return

retinString: 
        lw      $ra, 0($sp)     # Restore return address.
        addi    $sp, $sp, 4     # Restore stack pointer.
        jr      $ra            	# Return.
        
# 
#Description: output a string to the console 
#Internal registers used:  
#Declaration  outString(char *str) 
################
.globl outString 
outString:
        addi    $sp, $sp, -4   	# Make space on stack.
        sw      $ra, 0($sp)    	# Save return address.
           
        # simulator code to display string on console
        # a0 must contain pointer to string 
        li	$v0, 4  	# code for print string
        syscall                 # Print string .

retoutString: 
        lw      $ra, 0($sp)     # Restore return address.
        addi    $sp, $sp, 4     # Restore stack pointer.
        jr      $ra            	# Return.
        
# 
#Description: read an integer from the console 
#Internal registers used:  
#Declaration  (int num)inInt(void) 
############
.globl inInt 
inInt:
        addi 	$sp, $sp, -4    # Make space on stack.
        sw      $ra, 0($sp)     # Save return address.
           
        # simulator code to get integer from console
        li	$v0, 5  	# code for get integer
        syscall                 # get integer
        # integer is returned in $v0

retinInt: 
        lw      $ra, 0($sp)     # Restore return address.
        addi    $sp, $sp, 4     # Restore stack pointer.
        jr      $ra		# Return.

# 
#Description: output an integer to the console 
#Internal registers used:  
#Declaration  outInt(int) 
#############
.globl outInt 
outInt:
        addi    $sp, $sp, -4      # Make space on stack.
        sw      $ra, 0($sp)       # Save return address.
           
        # simulator code to display integer on console
        # $a0 must contain value to print 
        li	$v0, 1  	# code for print integer
        syscall                     # Print string .
        
retoutInt: 
        lw      $ra, 0($sp)     # Restore return address.
        addi    $sp, $sp, 4     # Restore stack pointer.
        jr      $ra            	# Return.

# 
#Description: read a floating point number from the console 
#Internal registers used:  
#Declaration  (fp num)inFP_S(void) 
############
.globl inFP_S 
inFP_S:
        addi 	$sp, $sp, -4    # Make space on stack.
        sw      $ra, 0($sp)     # Save return address.
           
        # simulator code to get integer from console
        li	$v0, 6		# code for get float number
        syscall                 # get integer
        # integer is returned in $v0

retinFP_S: 
        lw      $ra, 0($sp)     # Restore return address.
        addi    $sp, $sp, 4     # Restore stack pointer.
        jr      $ra		# Return.

# 
#Description: output an floating point number to the console 
#Internal registers used:  
#Declaration  outFP_S(fp) 
#############
.globl outFP_S 
outFP_S:
        addi    $sp, $sp, -4    # Make space on stack.
        sw      $ra, 0($sp)     # Save return address.
           
        # simulator code to display integer on console
        # $a0 must contain value to print 
        li	$v0, 2		# code for print float number
        syscall       		# Print string .
        
retoutFP_S: 
        lw      $ra, 0($sp)     # Restore return address.
        addi    $sp, $sp, 4     # Restore stack pointer.
        jr      $ra            	# Return.



#---------------------------Calculator subroutines------------------------------------
.globl addNum

##### ADDITION OPERATION
addNum:
	#{code to save return address to stack}
	addi	$sp, $sp, -4
	sw	$ra, ($sp)
	
	la	$a0, addPrompt
	jal 	outString
	
	ForAdd:
	
	la	$a0, addNum1
	jal 	outString
	
	jal	inInt
	move	$t0, $v0

	la	$a0, addNum2
	jal 	outString
	
	jal	inInt
	move	$t1, $v0
	
	add	$t2, $t0, $t1
	
	la	$a0, addResult
	jal	outString
	
	move	$a0, $t2
	jal	outInt
	
	la	$a0, addQuitComment
	jal	outString
	
	la	$a0, inputQuit1
	jal	inString
	lw	$t3, ($a0)
	
	lw	$t4, quit
	
	beq	$t3, $t4 , returnAddNum
	j	ForAdd
		
returnAddNum:
	#{code to restore return address from stack and return to main}
	lw	$ra, 0($sp)	# Restore return address.
	addi	$sp, $sp, 4	# Restore stack pointer.
	jr	$ra		# Return.


.globl	subNum

#### SUBTRACTION OPERATION	
subNum:
	#{code to save return address to stack}
	addi	$sp, $sp, -4
	sw	$ra, ($sp)
	
	la	$a0, subPrompt
	jal 	outString
	
ForSub:
	
	la	$a0, subNum1
	jal 	outString
	
	jal	inInt
	move	$t0, $v0

	la	$a0, subNum2
	jal 	outString
	
	jal	inInt
	move	$t1, $v0
	
	sub	$t2, $t0, $t1
	
	la	$a0, subResult
	jal	outString
	
	move	$a0, $t2
	jal	outInt
	
	la	$a0, subQuitComment
	jal	outString
	
	la	$a0, inputQuit1
	jal	inString
	lw	$t3, ($a0)
	
	lw	$t4, quit
	
	beq	$t3, $t4 , returnSubNum
	j	ForSub	

returnSubNum:
	#{code to restore return address from stack and return to main}
	lw	$ra, 0($sp)	# Restore return address.
	addi	$sp, $sp, 4	# Restore stack pointer.
	jr	$ra		# Return.
	

.globl	mulNum
#### MULTIPLICATION OPERATION	
mulNum:
	#{code to save return address to stack}
	addi	$sp, $sp, -4
	sw	$ra, ($sp)
	
	la	$a0, mulPrompt
	jal 	outString
	
ForMul:
	
	la	$a0, mulNum1
	jal 	outString
	
	jal	inInt
	move	$t0, $v0

	la	$a0, mulNum2
	jal 	outString
	
	jal	inInt
	move	$t1, $v0
	
	mul	$t2, $t0, $t1
	
	la	$a0, mulResult
	jal	outString
	
	move	$a0, $t2
	jal	outInt
	
	la	$a0, mulQuitComment
	jal	outString
	
	la	$a0, inputQuit1
	jal	inString
	lw	$t3, ($a0)
	
	lw	$t4, quit
	
	beq	$t3, $t4 , returnMulNum
	j	ForMul		

returnMulNum:
	#{code to restore return address from stack and return to main}
	lw	$ra, 0($sp)	# Restore return address.
	addi	$sp, $sp, 4	# Restore stack pointer.
	jr	$ra		# Return.	


.globl	divNum
#### DIVISION OPERATION	
divNum:
	#{code to save return address to stack}
	addi	$sp, $sp, -4
	sw	$ra, ($sp)
	
	la	$a0, divPrompt
	jal 	outString
ForDiv:
	
	la	$a0, divNum1
	jal 	outString
	
	jal	inInt
	move	$t0, $v0

	la	$a0, divNum2
	jal 	outString
	
	jal	inInt
	move	$t1, $v0
	
	div	$t2, $t0, $t1
	
	la	$a0, divResult
	jal	outString
	
	move	$a0, $t2
	jal	outInt
	
	la	$a0, divQuitComment
	jal	outString
	
	la	$a0, inputQuit1
	jal	inString
	lw	$t3, ($a0)
	
	lw	$t4, quit
	
	beq	$t3, $t4, returnDivNum
	j	ForDiv	
returnDivNum:
	#{code to restore return address from stack and return to main}
	lw	$ra, 0($sp)	# Restore return address.
	addi	$sp, $sp, 4	# Restore stack pointer.
	jr	$ra		# Return.

	

#---------------------------Command Processor-----------------------------------------

.globl procCmd

procCmd:
	la	$s0, cmdTable	 # get the address of the table
	#sub	$a0, $a0, 1	# if you want to start 	
	sll	$a0, $a0, 2	#register a0 contains the integer (menu option) so we want to multiply by 4
	add	$s0, $s0, $a0	#we want to jump to the adress in CMD TABLE where our instruction is located
	lw	$s1, 0($s0)	#load the insctrution(the label) that is located at the adress of $s0
	jr	$s1		#jump to the instruction whose address is in register $s1 
	
#---------------------------Exit Routine--MAIN----------------------------------------------	
.globl main
main:
	#code to save return address to stack}
	addi	$sp, $sp, -4	# Make space on stack.
	sw	$ra, 0($sp)	# Save return address.
	
	la	$a0, cmdPrompt	#load the adress of the cmdPrompt (message- menu) into a0 so it knows which message to put on the screen
	
mainWhile:
	jal 	outString	# put on the cmdPrompt(mesage - menu) on the screen
	
	jal	inInt
	move	$a0, $v0
	
	jal	procCmd
	la	$a0, cmdPrompt2	#load the adress of the cmdPrompt2 (message- menu) into a0 so it knows which message to put on the screen
	j	mainWhile
	
retMain:
	la	$a0, goodbyePrompt
	jal	outString
	li	$v0, 0		# Return zero.
	lw	$ra, 0($sp)	# Restore return address.
	addi	$sp, $sp, 4	# Restore stack pointer.
	
	jr	$ra

#--------------------------Data--------------------------------------------------------
.data

#Messagess(Prompts) for each operation
cmdPrompt: 	.asciiz "\n\nMy first Multifunctional Calculator, please be patient :)! \n \t0 - Exit \n \t1 - Addition \n \t2 - Subtraction \n \t3 - Multiplication \n \t4 - Division \n \t Select an operation > "
cmdPrompt2: 	.asciiz "\n\nDo you want to do other operations?:) \n \t0 - Exit \n \t1 - Addition \n \t2 - Subtraction \n \t3 - Multiplication \n \t4 - Division \n \t Select an operation > "
addPrompt:	.asciiz	"\n----Welcome to the Addition Subroutine----"
subPrompt:	.asciiz	"\n----Welcome to the Subtraction Subroutine----"
mulPrompt:	.asciiz	"\n----Welcome to the Multiplication Subroutine----"
divPrompt:	.asciiz	"\n----Welcome to the Division Subroutine----"
goodbyePrompt:	.asciiz "\n----Good Bye! Thank you for using my calculator:)----"

addNum1:	.asciiz "\nInput augend> "
addNum2:	.asciiz "Input the addend> "
addResult: 	.asciiz	"The result of the addition is > "
addQuitComment: .asciiz "\nPress ENTER to continue and ESC to go back to menu!"
inputQuit1:	.word 	0

subNum1:	.asciiz "\nInput minuend> "
subNum2:	.asciiz "Input the subtrahend> "
subResult: 	.asciiz	"The result of the subtraction is > "
subQuitComment: .asciiz "\nPress ENTER to continue and ESC to go back to menu!"
inputQuit2:	.word 	0

mulNum1:	.asciiz "\nInput multiplicand> "
mulNum2:	.asciiz "Input the multiplier> "
mulResult: 	.asciiz	"The result of the multiplication is > "
mulQuitComment: .asciiz "\nPress ENTER to continue and ESC to go back to menu!"
inputQuit3:	.word 	0

divNum1:	.asciiz "\nInput dividend> "
divNum2:	.asciiz "Input the divisor> "
divResult: 	.asciiz	"The result of the division is > "
divQuitComment: .asciiz "\nPress ENTER to continue and 'q' to go back to menu!"
inputQuit4:	.word 	0


#readStringBuf:	.space 256
#strLength:	.space 4

cmdTable:
	.word	retMain
	.word	addNum
	.word	subNum
	.word	mulNum
	.word	divNum


endl:	.asciiz "\n"
quit: .word 0x0a71
